import { SerialPort, SerialPortOpenOptions } from 'serialport'
type State = 'ready' | 'success' | 'error'
type EventName =
  | 'close'
  | 'data'
  | 'drain'
  | 'end'
  | 'error'
  | 'finish'
  | 'pause'
  | 'pipe'
  | 'readable'
  | 'resume'
  | 'unpipe'

interface Task {
  name: string
  command: string
  data: string
  state: State
  result: string
}

export const useSerialport = () => {
  let port: SerialPort | null = null
  let taskList: Task[] = []
  const isOpen = ref<boolean>(false)
  const isLoading = ref<boolean>(false)
  let timeOut = 3 * 1000
  let timeOutTimer: NodeJS.Timeout
  let count = 0
  let shouldContinue = true

  function open(options: SerialPortOpenOptions<Buffer>) {
    return new Promise((resolve, reject) => {
      port = new SerialPort(options, (err) => {
        if (err) return reject(err)
        resolve(port)
      })
    })
  }

  function close() {
    return new Promise((resolve, reject) => {
      port?.close((err) => {
        if (err) return reject(err)
        resolve(true)
      })
    })
  }

  function write(data: string | Buffer, encoding: BufferEncoding = 'utf-8', callback?: () => void) {
    return new Promise((resolve, reject) => {
      port?.write(data, encoding, (err) => {
        if (err) return reject(err)
        try {
          callback && callback()
        } catch (err) {
          return reject(err)
        }
      })
      port?.drain((err) => {
        if (err) return reject(err)
        console.log('发送数据完成')
        resolve(true)
      })
    })
  }

  function on(event: EventName, callback: (chunk: Buffer) => void) {
    port?.on(event, callback)
  }

  function addTask(task: Task) {
    task.state = 'ready'
    taskList.push(task)
  }

  function handleWrite() {
    timeOutTimer = setTimeout(() => {
      isLoading.value = false
      console.error('数据响应超时')
      Promise.reject('数据响应超时')
    }, timeOut)
  }

  function handleData(data: string | Buffer) {
    console.log('接受的数据：', data.toString())
    return true
  }

  async function handleTask() {
    if (!unref(isLoading) && taskList.length && shouldContinue) {
      let task = taskList[count]
      try {
        await write(task.data, 'utf-8', handleWrite)
      } catch (e) {
        isLoading.value = false
        task.state = 'error'
        shouldContinue = false
      }
    }
  }

  function handleOnData() {
    on('data', (chunk) => {
      clearTimeout(timeOutTimer)
      if (unref(isLoading)) {
        let flag = handleData(chunk)
        if (flag) {
          taskList[count].state = 'success'
          count++
          shouldContinue = true
          if (count == taskList.length) {
            count = 0
            console.log('消息队列已发送完成')
            return
          }
          handleTask()
        } else {
          taskList[count].state = 'error'
          shouldContinue = false
        }
      }
      isLoading.value = false
    })
  }

  return {
    port,
    open,
    close,
    write,
    on,
    addTask,
    handleTask,
    handleOnData
  }
}
